#include <string.h>

#include "statistics.h"
#include "regex.h"
#include "errno.h"
#include "stdio.h"
#include "stdlib.h"
#include "dirent.h"
#include <sys/stat.h>
#include <sys/types.h>

#include "strings.h" /* String utillity functions*/

typedef struct f_v_tr
{
    float v_tr;
    float v_tr_pdf;
} f_v_tr_type;

char *path_cat (const char *str1, char *str2) {
	size_t str1_len = strlen(str1);
	size_t str2_len = strlen(str2);
	char *result;
	result = malloc((str1_len+str2_len+1)*sizeof *result);
	strcpy (result,str1);
	int i,j;
	for(i=str1_len, j=0; ((i<(str1_len+str2_len)) && (j<str2_len));i++, j++) {
		result[i]=str2[j];
	}
	result[str1_len+str2_len]='\0';
	return result;
}

int token_file(char* short_file_name, char* name_pattern, char* delim, int** token_data, int token_data_size)
{
    int result = EXIT_FAILURE;

    char *name = strtok(short_file_name, delim);
    if (strcmp(name, name_pattern) == 0)
    {
        int i = 0;
        (*token_data) = (int*)malloc(token_data_size*sizeof(int));
        for (i = 0; i < token_data_size; i++)
        {
            char* digit = strtok(NULL, delim);
            (*token_data)[i] = atoi(digit);
            result = EXIT_SUCCESS;
        }
    }
    return result;
}

int statistics_get_v_tr_set(char* path_to_file,  gsl_matrix* v_tr_set, int row_processed)
{
    int allocation_step = 100;
    int num_of_v_tr_values = row_processed;
    int i = 0;

    
}

void* realloc_vector(void* old_vector, int num_of_actual_elements, int* current_size,
                        int alloc_step, int elem_size)
{
    if (num_of_actual_elements == *current_size)
    {
        void* new_vector = (void*)malloc(elem_size*(*current_size+alloc_step));
        
        memcpy(new_vector, old_vector, elem_size*(*current_size));
        *current_size = *current_size + alloc_step;
        free(old_vector);
        return new_vector;
    }
    else
    {
        return old_vector;
    }
}

int simple_comparsion(const void* first, const void* second)
{
    f_v_tr_type* f_first = (f_v_tr_type*)first;
    f_v_tr_type* f_second = (f_v_tr_type*)second;
    if (f_first->v_tr <=f_second->v_tr)
    {
        return -1;
    }
    else
    {
        return 1;
    }
}


int statistics_cat_files ( char* dir_path, char* dir_to_cat, char* name_pattern )
{
    struct dirent *dp;
    FILE* file;
    // enter existing path to directory below
    DIR *dir = opendir( dir_path );

    element_of_solution_t element_of_solution;

    while ( (dp = readdir( dir )) != NULL )
    {

        if ( dp->d_type == DT_REG )
        {
            int* token_data;
            char cp_file_name[MAXNAMLEN];

            strcpy(cp_file_name, dp->d_name);
            if (token_file(cp_file_name, name_pattern, "_", &token_data, 3) == EXIT_SUCCESS)
            {
               char *tmp;
               char new_file[MAXNAMLEN];
               int num_of_rows = 0;
               int i = 0;

               tmp =  path_cat(dir_path, dp->d_name);
               solver_read_element_of_solution_from_file( tmp, &element_of_solution );
               sprintf(new_file, "%s/%s_%d_%d.dat", dir_to_cat, name_pattern, token_data[1], token_data[2]);
               file = fopen(new_file, "a");

               num_of_rows = element_of_solution.num_of_rows;
               for (i = 0; i < num_of_rows; i++)
               {
                   double v_tr = gsl_matrix_get(element_of_solution.stat, i, ELEMENT_OF_SOLUTION_V_TR_VAL);
                   double v_tr_pdf = gsl_matrix_get(element_of_solution.stat, i, ELEMENT_OF_SOLUTION_V_TR_PDF);
                   fprintf(file, "%e\t%e\n", v_tr, v_tr_pdf);
               }
               fclose(file);
               free(tmp);
               tmp=NULL;
               solver_free_element_of_solution(&element_of_solution);
               free(token_data);
            }
        }
    }
    closedir( dir );
    return 0;
}

int statistics_get_v_tr_speed_distribution( char* dir_to_cat_files, char* name_pattern, int num_of_v_tr_steps)
{
    struct dirent *dp;
    FILE* file;
    // enter existing path to directory below
    DIR *dir = opendir( dir_to_cat_files );

   
    int alloc_step = 20000;
    
    
    
    double min_v_tr = 0;
    double max_v_tr = 0;
    double v_tr_step = 0;
    double v_tr = 0;
    int i = 0;
    char clean_cat_files[MAXNAMLEN];
    sprintf(clean_cat_files, "%s/%s/", dir_to_cat_files, "clean");
    mkdir(clean_cat_files, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);

    
    //v_tr_pdf_all_values = (double*)malloc(sizeof(double)*alloc_step);

    while ( (dp = readdir( dir )) != NULL )
    {

        if ( dp->d_type == DT_REG )
        {
            int* token_data = NULL;
            char cp_file_name[MAXNAMLEN];
            f_v_tr_type* new_f_v_tr_dirty = NULL;
            int num_of_actual_elements = 0;
            int current_size = alloc_step;
            int num_of_clean_elements = 0;
             f_v_tr_type* f_v_tr_dirty;
            f_v_tr_type* f_v_tr_clean;
            
            strcpy(cp_file_name, dp->d_name);
            if (token_file(cp_file_name, name_pattern, "_", &token_data, 2) == EXIT_SUCCESS)
            {
               char *cat_file;
               char new_cat_file[MAXNAMLEN];
               int i = 0;
               float v_tr = 0;
               float v_tr_pdf = 0;
               int start_index = 0;

               cat_file =  path_cat(dir_to_cat_files, dp->d_name);
               file = fopen(cat_file, "r");
               f_v_tr_dirty = (f_v_tr_type*)malloc(sizeof(f_v_tr_type)*alloc_step);

               while (fscanf(file, "%e\t%e\n", &v_tr, &v_tr_pdf) != EOF )
               {
                  

                   f_v_tr_dirty = (f_v_tr_type*)realloc_vector((void*)f_v_tr_dirty, num_of_actual_elements, &current_size, alloc_step, sizeof(f_v_tr_type));

                   //v_tr_pdf_all_values = realloc_vector(v_tr_all_values, num_of_actual_elements, &current_size, alloc_step);

                   f_v_tr_dirty[num_of_actual_elements].v_tr = v_tr;
                   f_v_tr_dirty[num_of_actual_elements].v_tr_pdf = v_tr_pdf;
                   num_of_actual_elements++;
               }
               fclose(file);
               file =fopen("/home/oddi/test.dat", "w");
               for (i=0; i < num_of_actual_elements; i++)
               {
                   fprintf(file, "%e\t%e\n", f_v_tr_dirty[i].v_tr, f_v_tr_dirty[i].v_tr_pdf);
               }
               fclose(file);
               qsort((void*)f_v_tr_dirty, num_of_actual_elements, sizeof(f_v_tr_type), *simple_comparsion);
               min_v_tr = f_v_tr_dirty[0].v_tr;
               max_v_tr = f_v_tr_dirty[num_of_actual_elements - 1].v_tr;
               
               v_tr_step = (max_v_tr - min_v_tr)/num_of_v_tr_steps;
               f_v_tr_clean = (f_v_tr_type*)malloc(sizeof(f_v_tr_type)*(num_of_v_tr_steps+1));
               
               for (v_tr = min_v_tr + 0.5*v_tr_step; v_tr < max_v_tr; v_tr += v_tr_step)
               {
                   int j = 0;
                   double v_tr_pdf = 0;
                   for (j = start_index; j < num_of_actual_elements; j++)
                   {
                       
                       if ((f_v_tr_dirty[j].v_tr <= v_tr + 0.5*v_tr_step) &&
                               (f_v_tr_dirty[j].v_tr >= v_tr - 0.5*v_tr_step))
                       {
                           v_tr_pdf += f_v_tr_dirty[j].v_tr_pdf;
                           
                       }
                       else
                       {
                           f_v_tr_clean[num_of_clean_elements].v_tr = v_tr;
                           f_v_tr_clean[num_of_clean_elements].v_tr_pdf = v_tr_pdf;
                           num_of_clean_elements++;
                           break;
                       }
                   }
                   start_index = j;
               }

               sprintf(new_cat_file, "%s/%s_%d_%d.dat", clean_cat_files, name_pattern, token_data[0], token_data[1]);
               file = fopen(new_cat_file, "w");
               for (i = 0; i < num_of_v_tr_steps; i++)
               {
                   fprintf(file, "%e\t%e\n", f_v_tr_clean[i].v_tr, f_v_tr_clean[i].v_tr_pdf);
               }
               fclose(file);
               free(token_data);
               free(f_v_tr_clean);
               free(f_v_tr_dirty);
            }
            
        }
    
    }
    
}



